﻿using AntdUI;
using Newtonsoft.Json;
using PosClient.Controls;
using PosClient.Helper;
using PosClient.Interfaces;
using PosClient.Job;
using PosClient.Job.DownLoad;
using PosClient.Model;
using PosClient.Service;
using PosClient.Service.Actives;
using PosClient.View.Report;
using PosClient.ViewModel;
using ReactiveUI;
using Splat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PosClient.View
{
    public partial class MainView : Window, IViewFor<MainViewModel>
    {
        private bool isLight = true;
        object IViewFor.ViewModel
        {
            get => ViewModel;
            set => ViewModel = (MainViewModel)value;
        }
        public MainViewModel ViewModel { get; set; }

        private static ScreenView screen;

        private delegate void SetDataDelegate();

        public KeepFocusHelper KeepFocusHelper;

        static System.Timers.Timer tickTimer = new System.Timers.Timer(1000);

        public MainView()
        {
            InitializeComponent();

            InitMenu();

            InitSetting();

            InitLocator();

            InitBinding();

            InitEvent();

            setupTickTimer();
        }

        private void InitMenu()
        {
            menu_base.Items.Clear();
            foreach (var item in DataUtil.MenuList)
            {
                var rootMenu = new AntdUI.MenuItem
                {
                    Text = item.Value.Text,
                    IconSvg = item.Value.IconSvg,
                    Tag = item.Value.Tag
                };
                menu_base.Items.Add(rootMenu);
            }
        }

        private void InitSetting()
        {
            //任务
            var job = Locator.Current.GetService<JobManager>();
            job.LoadJob();
        }

        private void InitLocator()
        {
            Locator.CurrentMutable.RegisterLazySingleton(() => new ActionService());
        }

        private void InitLoad()
        {
            KeepFocusHelper = new KeepFocusHelper(this, input_barcode);
            KeepFocusHelper.Start();

            label_store.Text = Globals.StoreName;
            label_pos.Text = Globals.Pos;

            //加个默认编码，为了测试
            input_barcode.Text = "0002818";

            //副屏
            screen = new ScreenView();
            screen.ShonOnMonitor();
        }

        private void InitEvent()
        {
            this.Load += MainView_Load;

            KeyDown += (s, e) =>
            {
                var actions = Locator.Current.GetService<ActionService>();
                IActionService action = actions.GetAction(e.KeyData);
                if (action != null && action.FormName() == this.Name)
                {
                    KeepFocusHelper.Stop();
                    action.Action(ViewModel);
                    KeepFocusHelper.Start();
                }
                if (e.KeyData == Keys.Enter)
                {
                    KeepFocusHelper.Stop();
                    if (!string.IsNullOrEmpty(input_barcode.Text))
                    {
                        ViewModel.GetPluCommand.Execute().Subscribe();
                    }
                    else if(ViewModel.PluList.Count > 0)
                    {
                        ViewModel.ConfirmPayCommand.Execute().Subscribe();
                    }
                    KeepFocusHelper.Start();
                }
                else if (e.KeyData == Keys.Escape)
                {
                    this.Close();
                }
            };

            this.FormClosing += (s, e) =>
            {
                var dialog = MessageBox.Show("确定要退出系统？", "操作提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                e.Cancel = !(DialogResult.Yes == dialog);
                if (!e.Cancel)
                {
                    tickTimer.Stop();
                    tickTimer.Close();
                }
            };

            menu_base.SelectChanged += (s, e) =>
            {
                //定制化内容，
                UserControl control = null;
                string name = e.Value.Tag.ToString();
                switch (name)
                {
                    case "ReportView":
                        control = new ReportView();
                        break;
                    default:
                        break;
                }
                if (control != null)
                {
                    AntdUI.Modal.Config config = AntdUI.Modal.config(this, "窗口", control);
                    config.Mask = true;
                    config.CloseIcon = true;
                    config.Padding = new System.Drawing.Size(6, 6);
                    config.BtnHeight = 0;
                    config.Keyboard = true;
                    AntdUI.Modal.open(config);
                }
                else
                {
                    AntdUI.Notification.Config config = new AntdUI.Notification.Config(this, "提醒", $"您点击了 {name}", TType.Success, TAlignFrom.Top);
                    AntdUI.Notification.open(config);
                }
            };

            button_collapse.Click += (s, e) =>
            {
                if (menu_base.Collapsed)
                {
                    menu_base.Width = (int)(125 * Config.Dpi);
                }
                else
                {
                    menu_base.Width = (int)(50 * Config.Dpi);
                }
                button_collapse.Toggle = !button_collapse.Toggle;
                menu_base.Collapsed = !menu_base.Collapsed;
            };

            this.KeyUp += (s, e) =>
            {
                pluGrid.PosGrid_KeyUp(e.KeyData);
                var actions = Locator.Current.GetService<ActionService>();
                IActionService action = actions.GetAction(e.KeyData);
                if (action != null && action.FormName() == this.Name)
                {
                    KeepFocusHelper.Stop();
                    action.Action(ViewModel);
                    KeepFocusHelper.Start();
                }
                if (e.KeyData == Keys.Left)
                {
                    ViewModel.AddOneCommand.Execute().Subscribe();
                }
                else if (e.KeyData == Keys.Right)
                {
                    ViewModel.DelOneCommand.Execute().Subscribe();
                }
            };

            this.FormClosed += (s, e) =>
            {
                Application.Exit();
                Environment.Exit(0);
            };

            this.numberKeyboard_lite.KeyboardEvent += (s, e) =>
            {
                Console.WriteLine(s);
                string key = s.ToString();
                switch (key)
                {
                    case "Dot":
                        key = ".";
                        break;
                    case "BACKSPACE":
                        key = "";
                        this.input_barcode.Text = this.input_barcode.Text.Substring(0, this.input_barcode.Text.Length - 1);
                        break;
                    case "Enter":
                        key = "";
                        if (ViewModel.PluList.Count > 0)
                        {
                            IActionService payView = new PayActive();
                            payView.Action(ViewModel);
                        };
                        break;
                }
                string text = input_barcode.Text;
                int index = input_barcode.SelectionStart;
                var changeText = text.Insert(index, key);
                input_barcode.Text = changeText;
                input_barcode.SelectionStart = index + key.Length;
                input_barcode.Focus();
               // input_barcode.Text += key;
            };

            ViewModel.PluList.ListChanged += (s, e) =>
            {
                pluGrid.DataSource_ListChanged(s, e);
            };

            pluGrid.GridIndexEvent += (s, e) =>
            {
                if (int.Parse(s.ToString()) < ViewModel.PluList.Count && int.Parse(s.ToString()) > -1)
                {
                    ViewModel.SelectPlu = ViewModel.PluList[int.Parse(s.ToString())];
                    ViewModel.Index = int.Parse(s.ToString());
                }
                else
                {
                    ViewModel.SelectPlu = new Plu(); 
                    ViewModel.Index = -1;
                }
            };

            pluGrid.GridDataEvent += (s, e) =>
            {
                if (s.ToString() == "+")
                {
                    ViewModel.AddOneCommand.Execute().Subscribe();
                }
                else if (s.ToString() == "-")
                {
                    ViewModel.DelOneCommand.Execute().Subscribe();
                }
                ViewModel.SummaryCommand.Execute().Subscribe();
            };

            button_light.Click += (s, e) =>
            {
                isLight = !isLight;
                //这里使用了Toggle属性切换图标
                button_light.Toggle = !isLight;
                button_data.Toggle = !isLight;
                Globals.IsLight = button_light.Toggle;
                ThemeHelper.SetColorMode(this, isLight);
            };

            button_data.Click += (s, e) =>
            {
                button_data.Loading = true;
                var loadTask = Task.Run(() =>
                {
                    BaseDataDownLoadJob baseJob = new BaseDataDownLoadJob();
                    baseJob.Excute();
                    var server = Locator.Current.GetService<JobManager>();
                    server.RunAllJob();
                });
                loadTask.ContinueWith(d =>
                {
                    if (d.IsFaulted)//任务出错
                    {
                        Logger.Default.Error(d.Exception.Message, d.Exception);
                        var config = new Notification.Config(this, "初始化提示", "初始化错误:" + d.Exception.Message, TType.Error, TAlignFrom.TR);
                        AntdUI.Notification.open(config);
                        button_data.Loading = false;
                    }
                    if (d.IsCompleted)//任务完成
                    {
                        button_data.Loading = false;
                    }
                    button_data.Loading = false;
                });
            };

            pluGrid.RowClickEvent += (s, e) =>
            {
                if (ViewModel.PluList.Count > 0)
                {
                    KeepFocusHelper.Stop();
                    ViewModel.ConfirmPayCommand.Execute().Subscribe();
                    KeepFocusHelper.Start();
                }
            };

            this.KeyPress += (s, e) =>
            {
                int key = Convert.ToInt32(e.KeyChar);
                // 数字、backspace、dot
                if (!(48 <= key && key <= 58 || key == 8 || key == 46))
                {
                    e.Handled = true;
                }
            };
        }

        private void InitBinding()
        {
            ViewModel = Locator.Current.GetService<MainViewModel>();
            this.WhenActivated(d =>
            {
                this.Bind(ViewModel,
                    vm => vm.PluList,
                    v => v.pluGrid.DataSource
                    ).DisposeWith(d);

                this.Bind(ViewModel,
                    vm => vm.Barcode,
                    v => v.input_barcode.Text
                    ).DisposeWith(d);

                // 应收金额绑定
                this.OneWayBind(ViewModel,
                    vm => vm.TotalAmount,
                    v => v.labelYsTotal.Text
                    ).DisposeWith(d);

                // 找零金额绑定
                this.OneWayBind(ViewModel,
                    vm => vm.ExchangeAmount,
                    v => v.labelExchangeAmount.Text
                    ).DisposeWith(d);

                // 待支付金额
                this.OneWayBind(ViewModel,
                    vm => vm.RemainPayAmount,
                    v => v.labelRemainPayAmount.Text
                    ).DisposeWith(d);

                // 合计优惠总额
                this.OneWayBind(ViewModel,
                    vm => vm.TotalDisAmount,
                    v => v.labelTotalDiscount.Text
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.Loading,
                    v => v.pageHeader_title.Loading
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.SubText,
                    v => v.pageHeader_title.SubText
                    ).DisposeWith(d);

                this.Bind(ViewModel,
                    vm => vm.OrderNo,
                    v => v.label_orderno.Text
                    ).DisposeWith(d);

                #region Vip

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase,
                    v => v.label_vipcode.Text,
                    ConvertVipCode
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase.VipLevel.LevelName,
                    v => v.label_viptype.Text
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase.GrowthCurrent,
                    v => v.label_growth.Text
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase.PointCurrent,
                    v => v.label_bonus.Text
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase.TicketCount,
                    v => v.label_ticket.Text
                    ).DisposeWith(d);

                this.OneWayBind(ViewModel,
                    vm => vm.VipBase.DepositCurrent,
                    v => v.label_deposit.Text
                    ).DisposeWith(d);

                #endregion

                #region BtnCommand

                this.BindCommand(ViewModel, vm => vm.RemoveCommand, v => v.btnRemove).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.SearchVipCommand, v => v.btnSearchMember).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.GetPluCommand, v => v.btnSeach).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.ChangePluPriceCommand, v => v.btnChangePrice).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.ClearCartCommand, v => v.btnClearCart).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.OpenPresentCommand, v => v.btnPresent).DisposeWith(d);
                this.BindCommand(ViewModel, vm => vm.OpenDownLoadCommand, v => v.btnDown).DisposeWith(d);

                #endregion

                #region WhenAnyValue

                ViewModel.WhenAnyValue(vm => vm.VipBase.Lables).Do(x =>
                {
                    if (x != null && x.Count > 0)
                    {
                        flowPanel_lables.Controls.Clear();
                        foreach (var lable in x)
                        {
                            AntdUI.Tag tag = new AntdUI.Tag();
                            tag.CloseIcon = false;
                            tag.Text = lable;
                            tag.AutoSize = true;
                            tag.Type = TTypeMini.Primary;
                            flowPanel_lables.Controls.Add(tag);
                        }
                    }
                }).Subscribe().DisposeWith(d);

                ViewModel.WhenAnyValue(vm => vm.Keyboards).Do(x => 
                {
                    var redis = FreeClient.Redis;
                    {
                        foreach (var control in flowPanel4.Controls)
                        {
                            if (control is AntdUI.Button)
                            {
                                var button = (control as AntdUI.Button);
                                string buttonName = button.Name;
                                var exists = redis.HExists(RedisKey.Redis_Keyboard, buttonName);
                                if (exists)
                                {
                                    var json = redis.HGet(RedisKey.Redis_Keyboard, buttonName);
                                    var action = Locator.Current.GetService<ActionService>();
                                    var keyboard = JsonConvert.DeserializeObject<Keyboard>(json);
                                    action.AddAction(keyboard);
                                    button.Text = $"{keyboard.KeyName}[{keyboard.KeyData}]";
                                }
                            }
                        }
                    }
                }).Subscribe().DisposeWith(d);

                ViewModel.WhenAnyValue(vm => vm.Index).Subscribe(x =>
                {
                    if (x > -1)
                    {
                        pluGrid.Index = x;
                    }
                }).DisposeWith(d);

                #endregion

                #region Subscribe

                ViewModel.GetPluCommand.Subscribe(result =>
                {
                    if (!result.Success)
                    {
                        var config1 = new AntdUI.Tooltip.Config(input_barcode, $"查询失败{result.Message}");
                        config1.ArrowAlign = AntdUI.TAlign.Top;
                        AntdUI.Tooltip.open(config1);
                    }
                    else
                    {
                        input_barcode.Clear();
                    }    
                    input_barcode.SelectAll();
                }).DisposeWith(d);

                #endregion

            });
        }

        private string ConvertVipCode(VipBase arg)
        {
            return arg.VipCode + "\r\n" + arg.VipName;
        }

        private void MainView_Load(object sender, EventArgs e)
        {
            InitLoad();
        }

        private void RefreshTime()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new SetDataDelegate(RefreshTime));
            }
            else
            {
                label_SystemDate.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            }
        }

        private void setupTickTimer()
        {
            tickTimer.AutoReset = true; //设置是执行一次（false）还是一直执行(true)
            tickTimer.Elapsed += (o, a) =>
            {
                RefreshTime();
            };
            tickTimer.Enabled = true;
        }

    }
}
